package com.smedi.ismedi.database.starter.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.yaml.snakeyaml.Yaml;
import lombok.extern.slf4j.Slf4j;
import freemarker.template.Template;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.sql.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * mp代码生成器
 *
 * @author yangzhenzhou
 * @since 2022/12/15
 */
@Slf4j
public class AutoGeneratorUtil {

    private static final String applicationService = "core.application.service";
    private static final String applicationServiceImpl = "core.application.service.impl";
    private static final String controller = "core.port.adapter.restful";
    private static final String entity = "core.port.adapter.persistence.model";
    private static final String mapper = "core.port.adapter.persistence.mybatis.mapper";


    public void autoGeneratorAndEmptyFile(AutoGeneratorParams autoGeneratorParams) {
        long startTime = System.currentTimeMillis();
        //mp代码生成器
        this.autoGenerator(autoGeneratorParams);
        //自定义文件生成
        this.createEmptyFileAndClass(autoGeneratorParams);
        //是否删除多余文件
        String[] alltabs = autoGeneratorParams.getTabs().split(",");
        if (StringUtils.isNotBlank(autoGeneratorParams.getApiTabs())) {
            try {
                String controllerPath = autoGeneratorParams.getOutPutDir() + File.separator + autoGeneratorParams.getParentName().replace(".", "\\") + File.separator + autoGeneratorParams.getModuleName() + File.separator + controller.replace(".", "\\");
                String applicationServicePath = autoGeneratorParams.getOutPutDir() + File.separator + autoGeneratorParams.getParentName().replace(".", "\\") + File.separator + autoGeneratorParams.getModuleName() + File.separator + applicationService.replace(".", "\\");
                String applicationServiceImplPath = autoGeneratorParams.getOutPutDir() + File.separator + autoGeneratorParams.getParentName().replace(".", "\\") + File.separator + autoGeneratorParams.getModuleName() + File.separator + applicationServiceImpl.replace(".", "\\");
                String mapperXmlPath = autoGeneratorParams.getMapperXmlUrl();
                Map<String, String> tempMap = autoGeneratorParams.getTableCommentMap();
                for (String str : alltabs) {
                    if (!tempMap.containsKey(str)) {
                        //删除多余文件，通过创建时间和文件名判断是否需要删除
                        String tabName = toUpperCasePre(lineToHump(StrUtil.unWrap(str, autoGeneratorParams.getPrefix(), autoGeneratorParams.getSuffix())));
                        Path controllerUrl = Paths.get(controllerPath + File.separator + tabName + "Controller.java");
                        Path serviceUrl = Paths.get(applicationServicePath + File.separator + tabName + "ApplicationService.java");
                        Path serviceImplUrl = Paths.get(applicationServiceImplPath + File.separator + tabName + "ApplicationServiceImpl.java");
                        Path xmlUrl = Paths.get(mapperXmlPath + File.separator + tabName + "Mapper.xml");

                        BasicFileAttributes controllerFile = Files.readAttributes(controllerUrl, BasicFileAttributes.class);
                        BasicFileAttributes serviceFile = Files.readAttributes(serviceUrl, BasicFileAttributes.class);
                        BasicFileAttributes serviceImplFile = Files.readAttributes(serviceImplUrl, BasicFileAttributes.class);
                        BasicFileAttributes mapperXmlFile = Files.readAttributes(xmlUrl, BasicFileAttributes.class);

                        long createControllerFileTime = controllerFile.creationTime().toMillis();
                        long createServiceFileTime = serviceFile.creationTime().toMillis();
                        long createServiceImplFileTime = serviceImplFile.creationTime().toMillis();
                        long createXmlFileTime = mapperXmlFile.creationTime().toMillis();

                        if (createControllerFileTime > startTime) {
                            Files.deleteIfExists(controllerUrl);
                        }
                        if (createServiceFileTime > startTime) {
                            Files.deleteIfExists(serviceUrl);
                        }
                        if (createServiceImplFileTime > startTime) {
                            Files.deleteIfExists(serviceImplUrl);
                        }
                        if (createXmlFileTime > startTime) {
                            Files.deleteIfExists(xmlUrl);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 自定义模块生成 controller、mapper、service、entity
     */
    public void autoGenerator(AutoGeneratorParams autoGeneratorParams) {
        String outPutDir = autoGeneratorParams.getOutPutDir();
        String moduleName = autoGeneratorParams.getModuleName();
        String parentName = autoGeneratorParams.getParentName();
        if (StringUtils.isBlank(moduleName)) {
            throw new RuntimeException("moduleName参数不能为空");
        }
        this.getDataParams(autoGeneratorParams);
        this.getTabs(autoGeneratorParams);

        String url = autoGeneratorParams.getUrl();
        String userName = autoGeneratorParams.getUserName();
        String password = autoGeneratorParams.getPassword();

        String[] tabsArr = autoGeneratorParams.getTabs().split(",");
        FastAutoGenerator.create(url, userName, password)
                .globalConfig(builder -> {
                    builder.author(autoGeneratorParams.getAuthor()) // 设置作者
                            .outputDir(outPutDir); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent(parentName) // 设置父包名
                            .moduleName(moduleName)
                            .service(applicationService)
                            .serviceImpl(applicationServiceImpl)
                            .controller(controller)
                            .entity(entity)
                            .mapper(mapper)
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, autoGeneratorParams.getMapperXmlUrl())); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.entityBuilder().enableLombok();
                    builder.mapperBuilder().enableMapperAnnotation().build();
                    builder.controllerBuilder().enableHyphenStyle();  // 开启驼峰转连字符
                    for (String tab : tabsArr) {
                        builder.addInclude(tab) // 设置需要生成的表名
                                .addTablePrefix(autoGeneratorParams.getPrefix()) // 设置过滤表前缀
                                .addFieldSuffix(autoGeneratorParams.getSuffix()); //设置过滤表后缀
                    }

                    //entity策略部分
                    builder.entityBuilder()
                            .convertFileName(entityName -> entityName + "Entity")
                            .disableSerialVersionUID() //禁用生成 serialVersionUID
                            .addSuperEntityColumns("id", "top_org_id", "tenant_id", "created_date", "version", "created_user_id", "latest_updated_date", "latest_updated_user_id", "is_deleted")
                            .enableLombok(); //开启lombok


                    //contoller策略
                    builder.controllerBuilder()
                            .enableRestStyle()
                            .convertFileName(entityName -> {
                                entityName += "Controller";
                                return entityName;
                            });
                    //service策略
                    builder.serviceBuilder()
                            .convertServiceFileName(entityName -> {
                                String serviceName = entityName;
                                serviceName += "ApplicationService";
                                return serviceName;
                            })
                            .convertServiceImplFileName(entityName -> {
                                String serviceImplName = entityName;
                                serviceImplName += "ApplicationServiceImpl";
                                return serviceImplName;
                            });
                })
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();
    }

    private void getTabs(AutoGeneratorParams autoGeneratorParams) {
        try {
            SimpleJdbcUtil simpleJdbcUtil = new SimpleJdbcUtil(autoGeneratorParams.getDriverClassName(), autoGeneratorParams.getUrl(), autoGeneratorParams.getUserName(), autoGeneratorParams.getPassword());
            Connection connection = simpleJdbcUtil.getConnection();
            String dbName = this.getDbName(autoGeneratorParams.getUrl());
            StringBuilder queryStr = new StringBuilder(" select table_name,table_comment from  information_schema.TABLES where TABLE_SCHEMA= ? and  table_name !='undo_log' ");
            if (StringUtils.isNotBlank(autoGeneratorParams.getTabs())) {

                queryStr.append(" and table_name in ( ");
                String[] arrays = autoGeneratorParams.getTabs().split(",");
                for (int i = 0; i < arrays.length; i++) {
                    queryStr.append(" ?,");
                }
                queryStr = new StringBuilder(queryStr.substring(0, queryStr.length() - 1));
                queryStr.append(" ) ");
            }
            PreparedStatement preparedStatement = connection.prepareStatement(queryStr.toString());
            preparedStatement.setString(1, dbName);
            if (StringUtils.isNotBlank(autoGeneratorParams.getTabs())) {
                String[] tabs = autoGeneratorParams.getTabs().split(",");
                for (int i = 2; i < tabs.length + 2; i++) {
                    preparedStatement.setString(i, tabs[i - 2]);
                }
            }
            ResultSet res = preparedStatement.executeQuery();
            StringBuilder tabBuff = new StringBuilder();
            Map<String, String> tempMap = new HashMap<>();
            Set<String> checkSet = new HashSet<>();
            if (StringUtils.isNotBlank(autoGeneratorParams.getApiTabs())) {
                Collections.addAll(checkSet, autoGeneratorParams.getApiTabs().split(","));
            }
            while (res.next()) {
                tabBuff.append(res.getString("table_name")).append(",");
                if (CollectionUtil.isEmpty(checkSet) || checkSet.contains(res.getString("table_name"))) {
                    tempMap.put(res.getString("table_name"), res.getString("table_comment"));

                }
            }
            if (tabBuff.length() > 0) {
                tabBuff.delete(tabBuff.length() - 1, tabBuff.length());
            }
            autoGeneratorParams.setTabs(tabBuff.toString());
            autoGeneratorParams.setTableCommentMap(tempMap);
        } catch (SQLException e) {
            throw new RuntimeException("获取表结构失败，请检查！");
        }

    }

    private String getDbName(String url) {
        Pattern p = Pattern.compile("jdbc:(?<db>\\w+):.*((//)|@)(?<host>.+):(?<port>\\d+)(/|(;DatabaseName=)|:)(?<dbName>\\w+)\\??.*");
        Matcher m = p.matcher(url);
        if (m.find()) {
            log.debug("获取表结构的目标库:" + m.group("dbName"));
            return m.group("dbName");
        }

        return null;
    }

    /**
     * 获取当前项目绝对路径下的配置文件
     * 默认路径为  项目名\项目名-core\src\main\resources\config\application-test.yml
     * config\application-test.yml部分可作为参数自定义改动
     */
    public DatasourceBean readYamlByFile(String filePath) {
        try {
            DatasourceBean datasourceBean = new DatasourceBean();
            String root = System.getProperty("user.dir");
            String[] files = root.split("\\\\");
            filePath = root + File.separator + files[files.length - 1] + "-core" + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + filePath;
            Map map = (Map) (new Yaml()).loadAs(new FileInputStream(filePath), HashMap.class).get("spring");
            if (map.containsKey("datasource")) {
                map = (Map) map.get("datasource");
                datasourceBean = JSON.parseObject(JSON.toJSONString(map), DatasourceBean.class);
            }
            return datasourceBean;
        } catch (FileNotFoundException var2) {
            log.error("默认配置文件读取异常", var2);
            return null;
        }
    }

    private DatasourceBean readYamlByClass(String config) {
        DatasourceBean datasourceBean = new DatasourceBean();
        YamlPropertiesFactoryBean yamlMapFactoryBean = new YamlPropertiesFactoryBean();
        yamlMapFactoryBean.setResources(new ClassPathResource(config));
        Properties properties = yamlMapFactoryBean.getObject();
        if (properties != null) {
            datasourceBean.setUrl(properties.getProperty("spring.datasource.url"));
            datasourceBean.setUsername(properties.getProperty("spring.datasource.username"));
            datasourceBean.setPassword(properties.getProperty("spring.datasource.password"));
        }
        return datasourceBean;
    }

    private void getDataParams(AutoGeneratorParams autoGeneratorParams) {
        String url = autoGeneratorParams.getUrl();
        String userName = autoGeneratorParams.getUserName();
        String password = autoGeneratorParams.getPassword();
        if (StringUtils.isBlank(url) || StringUtils.isBlank(userName) || StringUtils.isBlank(password)) {
            log.debug("未输入url、username、password参数,当前configPath地址为:" + autoGeneratorParams.getConfigPath());
            DatasourceBean datasourceBean = this.readYamlByFile(autoGeneratorParams.getConfigPath());
            if (StringUtils.isBlank(url)) {
                autoGeneratorParams.setUrl(datasourceBean.getUrl());
            }
            if (StringUtils.isBlank(userName)) {
                autoGeneratorParams.setUserName(datasourceBean.getUsername());
            }
            if (StringUtils.isBlank(password)) {
                autoGeneratorParams.setPassword(datasourceBean.getPassword());
            }
        }
        if (StringUtils.isBlank(autoGeneratorParams.getUrl()) || StringUtils.isBlank(autoGeneratorParams.getUserName()) || StringUtils.isBlank(autoGeneratorParams.getPassword())) {
            throw new RuntimeException("未输入数据库url、name、password参数，且获取本地配置文件失败!");
        }
    }

    private void createEmptyFileAndClass(AutoGeneratorParams autoGeneratorParams) {
        String parentName = autoGeneratorParams.getParentName();
        String outPutDir = autoGeneratorParams.getOutPutDir();
        String moduleName = autoGeneratorParams.getModuleName();
        String outPutApiDir = autoGeneratorParams.getOutPutApiDir();

        log.info("==========================开始创建目录结构类==========================");
        String parentNameUrl = parentName.replace(".", "\\");
        //request
        File requestFile = new File(outPutApiDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "api" + File.separator + "dto" + File.separator + "request");
        if (requestFile.mkdirs()) {
            log.info(outPutApiDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "api" + File.separator + "feign 创建成功");
        }
        //response
        File responseFile = new File(outPutApiDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "api" + File.separator + "dto" + File.separator + "response");
        if (responseFile.mkdirs()) {
            log.info(outPutApiDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "api" + File.separator + "feign 创建成功");
        }
        //feign
        File feignFile = new File(outPutApiDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "api" + File.separator + "feign");
        if (feignFile.mkdirs()) {
            log.info(outPutApiDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "api" + File.separator + "feign 创建成功");
        }

        //application.command
        File applicationCommand = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + "" + File.separator + "core" + File.separator + "application" + File.separator + "command");
        if (applicationCommand.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "application" + File.separator + "command 创建成功");
        }

        //application.convert
        File applicationConvert = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "application" + File.separator + "convert");
        if (applicationConvert.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "application" + File.separator + "convert 创建成功");
        }
        //application.query.impl
        File applicationQuery = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "application" + File.separator + "query");
        File applicationQueryImpl = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "application" + File.separator + "query" + File.separator + "impl");
        if (applicationQueryImpl.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "application" + File.separator + "query" + File.separator + "impl 创建成功");
        }


        //application.query.vo
        File applicationQueryVo = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "application" + File.separator + "query" + File.separator + "vo");
        if (applicationQueryVo.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "application" + File.separator + "query" + File.separator + "vo 创建成功");
        }

        //domain.aggregatemodel
        File domainAggregatemodel = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "domain" + File.separator + "aggregatemodel");
        if (domainAggregatemodel.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "domain" + File.separator + "aggregatemodel 创建成功");
        }

        //domain.dto
        File domainDto = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "domain" + File.separator + "dto");
        if (domainDto.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "domain" + File.separator + "dto 创建成功");
        }

        //domain.repository
        File domainRepository = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "domain" + File.separator + "repository");
        if (domainRepository.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "domain" + File.separator + "repository 创建成功");
        }

        //service.impl
        File domainService = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "domain" + File.separator + "service");
        File domainServiceImpl = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "domain" + File.separator + "service" + File.separator + "impl");
        if (domainServiceImpl.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "domain" + File.separator + "service" + File.separator + "impl 创建成功");
        }

        //infrastructure.constant
        File infrastructureConstant = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "infrastructure" + File.separator + "constant");
        if (infrastructureConstant.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "infrastructure" + File.separator + "constant 创建成功");
        }

        //infrastructure.handler
        File infrastructureHandler = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "infrastructure" + File.separator + "handler");
        if (infrastructureHandler.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "infrastructure" + File.separator + "handler 创建成功");
        }

        //util
        File infrastructureUtil = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "infrastructure" + File.separator + "util");
        if (infrastructureUtil.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "infrastructure" + File.separator + "util 创建成功");
        }

        //validator
        File infrastructureValidator = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "infrastructure" + File.separator + "validator");
        if (infrastructureValidator.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "infrastructure" + File.separator + "validator 创建成功");
        }

        //port.adapter.convert
        File adapterConvert = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "port" + File.separator + "adapter" + File.separator + "convert");
        if (adapterConvert.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "port" + File.separator + "adapter" + File.separator + "convert 创建成功");
        }

        //port.adapter.persistence.repository.impl
        File repositoryImpl = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "port" + File.separator + "adapter" + File.separator + "persistence" + File.separator + "repository" + File.separator + "impl");
        if (repositoryImpl.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "port" + File.separator + "adapter" + File.separator + "persistence" + File.separator + "repository" + File.separator + "impl 创建成功");
        }

        //port.adapter.persistence.service.impl
        File persistenceImpl = new File(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "port" + File.separator + "adapter" + File.separator + "service" + File.separator + "impl");
        if (persistenceImpl.mkdirs()) {
            log.info(outPutDir + File.separator + parentNameUrl + File.separator + moduleName + File.separator + "core" + File.separator + "port" + File.separator + "adapter" + File.separator + "service" + File.separator + "impl 创建成功");
        }

        String[] flags = {"add", "del", "update", "queryPage", "queryOne", "queryList"};
        Map<String, Object> params = new HashMap<>();
        Map<String, String> tempMap = autoGeneratorParams.getTableCommentMap();
        if (null == tempMap || tempMap.size() == 0) {
            return;
        }
        params.put("moduleName", autoGeneratorParams.getModuleName());
        params.put("author", autoGeneratorParams.getAuthor());
        params.put("date", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        params.put("parentName", autoGeneratorParams.getParentName());
        List<String> tableNames = new ArrayList<>();
        for (String tab : tempMap.keySet()) {
            String tabName = toUpperCasePre(lineToHump(StrUtil.unWrap(tab, autoGeneratorParams.getPrefix(), autoGeneratorParams.getSuffix())));
            tableNames.add(tabName);
            params.put("tableName", tabName);
            params.put("tableComment", tempMap.get(tab));
            for (String str : flags) {
                String requestFileName = tabName;
                String commandFileName = tabName;
                String modelFileName = tabName;
                switch (str) {
                    case "add":
                        requestFileName = "Add" + requestFileName + "Request.java";
                        commandFileName = "Add" + commandFileName + "Command.java";
                        modelFileName = modelFileName + ".java";
                        break;
                    case "del":
                        requestFileName = "Del" + requestFileName + "Request.java";
                        commandFileName = "Del" + commandFileName + "Command.java";
                        modelFileName = "Del" + modelFileName + ".java";
                        break;
                    case "update":
                        requestFileName = "Update" + requestFileName + "Request.java";
                        commandFileName = "Update" + commandFileName + "Command.java";
                        modelFileName = modelFileName + ".java";
                        break;
                    case "queryPage":
                        requestFileName = "Query" + requestFileName + "PageRequest.java";
                        commandFileName = "Query" + commandFileName + "PageCommand.java";
                        modelFileName = "Query" + modelFileName + "Page.java";
                        break;
                    case "queryOne":
                        requestFileName = "Query" + requestFileName + "ByOneRequest.java";
                        commandFileName = "Query" + commandFileName + "ByOneCommand.java";
                        modelFileName = "Query" + modelFileName + "ByOne.java";
                        break;
                    case "queryList":
                        requestFileName = "Query" + requestFileName + "ListRequest.java";
                        commandFileName = "Query" + commandFileName + "ListCommand.java";
                        modelFileName = "Query" + modelFileName + "List.java";
                        break;
                }
                params.put("flag", str);
                //reuqest
                createFileByTemplate(params, "apiRequest.java.ftl", requestFile.getPath(), requestFileName);
                //command
                createFileByTemplate(params, "command.java.ftl", applicationCommand.getPath(), commandFileName);
                //domain.aggregatemodel
                createFileByTemplate(params, "aggregatemodel.java.ftl", domainAggregatemodel.getPath(), modelFileName);

            }
            //feign
            createFileByTemplate(params, "feignApi.java.ftl", feignFile.getPath(), "Remote" + tabName + "FeignApi.java");
            //response
            createFileByTemplate(params, "apiResponse.java.ftl", responseFile.getPath(), tabName + "Response.java");
            //application.query
            createFileByTemplate(params, "queryService.java.ftl", applicationQuery.getPath(), tabName + "QueryService.java");
            //application.query.impl
            createFileByTemplate(params, "queryServiceImpl.java.ftl", applicationQueryImpl.getPath(), tabName + "QueryServiceImpl.java");
            //application.query.vo
            createFileByTemplate(params, "queryVo.java.ftl", applicationQueryVo.getPath(), tabName + "QueryVo.java");
            //domain.repository
            createFileByTemplate(params, "repository.java.ftl", domainRepository.getPath(), tabName + "Repository.java");
            //infrastructure.constant
            createFileByTemplate(params, "constantField.java.ftl", infrastructureConstant.getPath(), "ConstantField.java");
            createFileByTemplate(params, "customError.java.ftl", infrastructureConstant.getPath(), "CustomError.java");
            //port.adapter.persistence.repository.impl
            createFileByTemplate(params, "repositoryImpl.java.ftl", repositoryImpl.getPath(), tabName + "RepositoryImpl.java");
            //domainService
            createFileByTemplate(params, "domainService.java.ftl", domainService.getPath(), tabName + "DomainService.java");
            //domainServiceImpl
            createFileByTemplate(params, "domainServiceImpl.java.ftl", domainServiceImpl.getPath(), tabName + "DomainServiceImpl.java");
            //domain.dto
            createFileByTemplate(params, "dtoquery.java.ftl", domainDto.getPath(), tabName + "Query.java");

        }

        //port.adapter.convert
        params.put("tableNames", tableNames);
        createFileByTemplate(params, "adapterConverter.java.ftl", adapterConvert.getPath(), "AdapterConverter.java");

        //application.convert
        createFileByTemplate(params, "appConverter.java.ftl", applicationConvert.getPath(), "AppConverter.java");
        log.info("==========================目录结构类创建完成==========================");

    }

    public static String toUpperCasePre(String name) {
        char[] chars = name.toCharArray();
        if (97 <= chars[0] && chars[0] <= 122) {
            chars[0] ^= 32;
        }
        return String.valueOf(chars);
    }

    public static String lineToHump(String str) {
        str = str.toLowerCase();
        Pattern linePattern = Pattern.compile("_(\\w)");
        Matcher matcher = linePattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    private static void createFileByTemplate(Map<String, Object> valueMap, String useTemplateName,
                                             String outPutPath, String fileName) {
        try {
            final String ENCODING = "UTF-8";

            Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
            cfg.setTemplateLoader(new ClassTemplateLoader(AutoGeneratorUtil.class, "/templates/"));
            cfg.setEncoding(Locale.getDefault(), ENCODING);

            // 指定使用的模板
            Template template = cfg.getTemplate(useTemplateName, ENCODING);
            template.setEncoding(ENCODING);

            File filePath = new File(outPutPath);
            if (!filePath.exists()) {
                filePath.mkdirs();
            }

            // 生成的代码位置和名字
            File targetFile = new File(outPutPath + File.separator + fileName);
            if (targetFile.exists()) { //不进行覆盖
                return;
            }
            template.process(valueMap, new OutputStreamWriter(new FileOutputStream(outPutPath + File.separator + fileName, false), ENCODING));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //调用 demo
//    public static void main(String[] args) {
//        AutoGeneratorUtil autoGeneratorUtil = new AutoGeneratorUtil();
//        AutoGeneratorParams autoGeneratorParams = AutoGeneratorParams.builder()
//                //.url("jdbc:mysql://10.96.100.153:3306/smedi_quality?useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&characterEncoding=utf-8")
//                //.userName("root") // 数据库名 选填，默认读取配置文件
//                //.password("smedismedi") //数据库密码 选填，默认读取配置文件
//                .moduleName("quality") //模块名称 必填
//                //.configPath("config\\application-test.yml")配置文件地址 选填，默认读取地址为resources下config/application-test.yml
//                //.tabs("qlt_quality_check,qlt_hidden_danger,qlt_instrument") //表 选填，默认生成目标库所有表
//                //.outPutDir("D:\\epc-project\\ismedi-demo\\ismedi-demo-core\\src\\main\\java")// 输出目录 选填 默认为 项目\项目-core\src\main\java
//                //.mapperXmlUrl("D:\\epc-project\\ismedi-demo\\ismedi-demo-core\\src\\main\\resources\\myBatisMapping") //mapperxml位置 选填
//                //.parentName("com.smedi.ismedi") //父包名 选填 默认为com.smedi.ismedi
//                .prefix("qlt_") //去除前缀 选填 默认为空
//                //.suffix("") //去除后缀 选填 默认为空
//                //.author("作者") //作者 选填 默认为AutoGenerator
//                .apiTabs("qlt_quality_check,qlt_hidden_danger,qlt_instrument")//生成增删改查接口的表,默认为所有表生成模板接口
//                .build();
//        autoGeneratorUtil.autoGeneratorAndEmptyFile(autoGeneratorParams);
//
//    }

}
